﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using Utility;
using Model;
using Model.Modules;
using System.Data.Entity;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Configuration;
using System.Timers;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Collections.Concurrent;
using System.Threading;
using Newtonsoft.Json;
using Google.Protobuf.WellKnownTypes;
using System.Collections.Specialized;
using ViewModel.VM.Control;
using System.Data.Entity.Migrations;
using MySql.Data.MySqlClient;
using System.Net.Http;
using System.Net;
using Microsoft.AspNet.SignalR.Client;
using FluentScheduler;
using System.IO;
using System.Windows.Documents;
using Proxy;

namespace ViewModel
{
    public class VM_PageMain : BaseViewModel
    {
        #region 变量
        public static surfacedetectEntities surfaceEntities;

        public bool LiveIsRefreshing { get { return liveisRefreshing; } set { liveisRefreshing = value; OnPropertyChanged(); } }
        private bool liveisRefreshing;

        public int CurrentImageType
        {
            get { return currentImageType; }
            set
            {
                currentImageType = value;
                OnPropertyChanged();
                if (CurrentImg == null)
                    return;
                new DefectDataHelper().setCurrentImageByImageType(new List<Imagedefectinfo>() { CurrentImg }, CurrentImageType);
                var tempimg = CurrentImg;
                CurrentImg = null;
                CurrentImg = tempimg;
            }
        }
        private int currentImageType;

        public ObservableCollection<image> Imagelist { get { return imagelist; } set { imagelist = value; OnPropertyChanged(); } }
        private ObservableCollection<image> imagelist;

        public ObservableCollection<image_defect> Defectlist { get { return defectlist; } set { defectlist = value; OnPropertyChanged(); } }
        private ObservableCollection<image_defect> defectlist;



        public ObservableRangeCollection<Imagedefectinfo> ImageDefectlist { get { return imagedefectlist; } set { imagedefectlist = value; OnPropertyChanged(); } }
        private ObservableRangeCollection<Imagedefectinfo> imagedefectlist;



        public ObservableCollection<ObservableCollection<steel_defect>> SteelDefectlist { get { return steeldefectrangelist; } set { steeldefectrangelist = value; OnPropertyChanged(); } }
        private ObservableCollection<ObservableCollection<steel_defect>> steeldefectrangelist;
        public ObservableCollection<ObservableCollection<steel_defect>> SteelDefectlistView { get { return steeldefectrangelistView; } set { steeldefectrangelistView = value; OnPropertyChanged(); } }
        private ObservableCollection<ObservableCollection<steel_defect>> steeldefectrangelistView;


        public ObservableCollection<defectsubtotalbytype> SubtotalByTypelist { get { return subtotalByTypelist; } set { subtotalByTypelist = value; OnPropertyChanged(); } }
        private ObservableCollection<defectsubtotalbytype> subtotalByTypelist;

        public ObservableCollection<Imagedefectinfo> Currentlist { get { return currentlist; } set { currentlist = value; OnPropertyChanged(); } }
        private ObservableCollection<Imagedefectinfo> currentlist;

        public bool HasAlertInfo { get { return hasAlertInfo; } set { hasAlertInfo = value; OnPropertyChanged(); } }
        private bool hasAlertInfo;

        public bool ShowAlert { get { return showAlert; } set { showAlert = value; OnPropertyChanged(); updateShowAlertStatus(); } }
        private bool showAlert;
        

        public steel_defect CurrentSteelDefect
        {
            get { return currentSteelDefect; }
            set
            {
                currentSteelDefect = value; OnPropertyChanged();
                updateCurrentImage();
            }
        }
        private steel_defect currentSteelDefect;

        public Imagedefectinfo CurrentImg
        {
            get { return currentImg; }
            set
            {
                currentImg = value; OnPropertyChanged();
            }
        }
        private Imagedefectinfo currentImg;



        public image_defect CurrentDefect { get { return currentDefect; } set { currentDefect = value; OnPropertyChanged(); } }
        private image_defect currentDefect;

        public ObservableCollection<batch> Batchlist { get { return batchlist; } set { batchlist = value; OnPropertyChanged(); } }
        private ObservableCollection<batch> batchlist;

        public batch CurrentBatch
        {
            get { return currentBatch; }
            set { currentBatch = value; OnPropertyChanged(); }
        }
        private batch currentBatch;

        public int CurrentLeftEdge
        {
            get { return currentLeftEdge; }
            set { currentLeftEdge = value; OnPropertyChanged(); }
        }
        private int currentLeftEdge;

        public string RunningStatus
        {
            get { return runningStatus; }
            set { runningStatus = value; OnPropertyChanged(); }
        }
        private string runningStatus;



        public int CurrentCamera { get { return currentCamera; } set { currentCamera = value; OnPropertyChanged(); } }
        private int currentCamera;

        public string Message { get { return message; } set { message = value; OnPropertyChanged(); } }
        private string message;

        public int IgnoreCount { get { return ignoreCount; } set { ignoreCount = value; OnPropertyChanged(); } }
        private int ignoreCount;
        public int WarningCount { get { return warningCount; } set { warningCount = value; OnPropertyChanged(); } }
        private int warningCount;
        public int AlertCount { get { return alertCount; } set { alertCount = value; OnPropertyChanged(); } }
        private int alertCount;
        public FullyObservableCollection<AlertInfo> AlertInfos { get { return alertInfos; } set { alertInfos = value; OnPropertyChanged(); } }
        private FullyObservableCollection<AlertInfo> alertInfos;

        public ObservableCollection<AlertInfo> CurrentAlertInfo { get; set; }


        public Object ProcessingCount { get { return processingCount; } set { processingCount = value; OnPropertyChanged(); } }
        private Object processingCount;

        public ObservableCollection<int[]> AnnoPoints { get { return annoPoints; } set { annoPoints = value; OnPropertyChanged(); } }
        private ObservableCollection<int[]> annoPoints;

        public bool ShowFloatViewer { get;set; }


        public System.Timers.Timer timer;

        ESDataHelper eshelper;
        int Onlineimagescount = 24;
        int essearchcount = 512;
        DataFrom database = DataFrom.Test;
        ImagesFactoryOnline imagesFactory;
        ImagesFactoryOnline imagesFactoryHistory;
        DateTime? latestDefectInsertTime = null;
        DateTime? latestSteelDefectInsertTime = null;
        DefectDataHelper defectDataHelper;
        bool AutoRefreshCurrentImg = false;
        #endregion



        public VM_PageMain()
        {
            int Interval = int.Parse(ConfigurationManager.AppSettings["interval"]);
            Onlineimagescount = int.Parse(ConfigurationManager.AppSettings["onlineimagesize"]);

            var databasestr = ConfigurationManager.AppSettings["database"];
            database = ConfigurationManager.AppSettings["database"] == "es" ? DataFrom.ES : ConfigurationManager.AppSettings["database"] == "mysql" ? DataFrom.Mysql : DataFrom.Test;
            Logger.Info("StartInitData");
            InitData();
            Logger.Info("StartInitWSclient");

            Logger.Info("InitSuccess");
            timer = new System.Timers.Timer();
            timer.Interval = Interval;
            timer.Elapsed += Timer_Elapsed;

            timer.Start();

            if (database == DataFrom.Test)
            {
                var timer1 = new System.Timers.Timer();
                timer1.Interval = 100;
                timer1.Elapsed += (s, e) =>
                {

                    if (Application.Current != null)
                        System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            //var r = new Random();
                            //AnnoPoints.Add(new int[] { 0, r.Next(1, 5), r.Next(0, 500), 4 });
                            if (CurrentLeftEdge < 600000)
                                CurrentLeftEdge = CurrentLeftEdge + 50;
                        }));
                    var dt = DateTime.Now;
                    if (dt.Second % 10 == 0)
                    {
                        DoMenthodByDispatcher(() =>
                        {
                            AlertInfos.Insert(0, new AlertInfo() { id = Guid.NewGuid().ToString(), main_id = "X0309135902", msg_type =Msg_type.steel_defect, msg_id = "xxxxx", insert_time = DateTime.Now, message = new Random().NextDouble() > 0.5 ? $"{DateTime.Now.ToLongDateString()}又发现了一个个新缺陷水电费水电费水电费的司法送达新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手个新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手个新缺陷水电费新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手个新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手个新缺陷水电费发撒东发手打发撒东发手个新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手个新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手新缺陷水电费水电费水电费的司法送达发撒东发手打发撒东发手打" : "新缺陷水电费水电费水电费" });
                        });
                    }
                };
                timer1.Start();
            }
        }



        #region init 初始化相关代码
        private void InitData()
        {
            try
            {
                ShowAlert=true;
                HasAlertInfo = false;
                AlertSeriesHelper.initAlertDevice(ConfigHelper.GetConfig("serialPortName"), null);
                surfaceEntities = new surfacedetectEntities();
                LiveIsRefreshing = true;
                CurrentImageType = 1;
                ShowFloatViewer = false;

                Currentlist = new ObservableCollection<Imagedefectinfo>();
                ImageDefectlist = new ObservableRangeCollection<Imagedefectinfo>();
                SteelDefectlist = new ObservableCollection<ObservableCollection<steel_defect>>();
                SteelDefectlistView = new ObservableCollection<ObservableCollection<steel_defect>>();
                AlertInfos = new FullyObservableCollection<AlertInfo>();
                SubtotalByTypelist = new ObservableCollection<defectsubtotalbytype>();
                AlertInfos.CollectionChanged += (s, e) =>
                {
                    if (AlertInfos.Where(t => t.confirmed == false).Count() > 0)
                    {

                        AlertSeriesHelper.sendData("41");
                        HasAlertInfo = true;
                    }
                    else
                    {
                        AlertSeriesHelper.sendData("21");
                        HasAlertInfo = false;
                    }

                };
                AlertInfos.ItemPropertyChanged += (s, e) =>
                {
                    if (e.PropertyName == "confirmed")
                    {
                        if (AlertInfos.Where(t => t.confirmed == false).Count() == 0)
                        {
                            AlertSeriesHelper.sendData("21");
                            HasAlertInfo = false;
                        }
                    }
                };
                //CurrentDefectFilter = new DefectFilterModel();

                Batchlist = new ObservableCollection<batch>();

                imagesFactory = new ImagesFactoryOnline(PageName.PageMain, InsertAt.Top, 120, Currentlist, Batchlist, ProcessingCount);
                imagesFactory.Run();
                ProcessingCount = 50;

                AnnoPoints = new ObservableCollection<int[]>();
                defectDataHelper = new DefectDataHelper();


                SteelDefectlist.CollectionChanged += (s, e) =>
                {
                    if (e.Action == NotifyCollectionChangedAction.Add)
                    {
                        SteelDefectlistView.Add(SteelDefectFilterHelper.GetFilteredSteelDefects(e.NewItems[0] as ObservableCollection<steel_defect>, StaticData.CurrentDefectFilter));
                    }
                    else if (e.Action == NotifyCollectionChangedAction.Reset)
                    {
                        SteelDefectlistView.Clear();
                    }
                    CalcSubtotalByType();
                };
                eshelper = new ESDataHelper();
                LoadAlertInfos();

            }
            catch (Exception e)
            {
                Logger.Error(e);
            }

            //初始化定时任务
            JobManager.Initialize();
            JobManager.AddJob(() =>
            {
                autoDeleteMessage();

            }, s => s.ToRunEvery(2).Minutes());
            JobManager.Start();
        }

        public static String UserName { get; set; }
        public HubConnection Connection { get; set; }
        public IHubProxy HubProxy { get; set; }
        private async Task ConnectHubAsync()
        {
            Logger.Info("Starting SignalRClient");
            UserName = "csole";
            var wsserverurl = System.Configuration.ConfigurationManager.AppSettings["wssaddress"];
            Connection = new HubConnection($"http://{wsserverurl}:8093/signalr");
            HubProxy = Connection.CreateHubProxy("AlertInfoHub");
            //Handle incoming event from server: use Invoke to write to console from SignalR's thread
            HubProxy.On<string, string>("AddMessage", (name, message) =>
            {
                DoMenthodByDispatcher(new Action(() =>
                {
                    var alertinfo = JsonConvert.DeserializeObject<AlertInfo>(message);
                    AlertInfos.Insert(0, alertinfo);
                }));
            });
            try
            {
                await Connection.Start();
            }
            catch (HttpRequestException e)
            {
                Logger.Info($"signalR连接失败:{e.Message}");
                //No connection: Don't enable Send button or show chat UI
                return;
            }
        }

        #endregion


        #region 按时间间隔update更新数据相关代码

        bool ISFirst = true;
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (StaticData.IsRefreshing && StaticData.ActivePage == PageName.PageMain)
            {
                try
                {
                    UpdateImageData();
                    ISFirst = false;
                }
                catch (Exception ee)
                {
                    Logger.Error(ee);
                }
            }
            else
            {
                ISFirst = true;
            }
        }

        private async void UpdateImageData()
        {
            updateBatchList();
            await QueryUpdateImageInfo();
            updateAlertCount();
        }

        private void updateBatchList()
        {
            if (StaticData.DataBase == DataFrom.Test)
                insertOrUpdateTestBatch();//测试模式的话，根据配置给数据库添加新批次或更新批次信息

            if (!Batchlist.Any())
            {
                using (surfacedetectEntities surfaceEntities = new surfacedetectEntities())
                {
                    Batchlist = new ObservableCollection<batch>(surfaceEntities.batch.AsNoTracking().OrderByDescending(o => o.insert_time).Take(1).ToList());
                }

                CurrentBatch = Batchlist.First();
                updateSpeed();
            }
            else
            {
                var maxid = Batchlist.Max(m => m.id);
                var newlist=new List<batch>();
                using (surfacedetectEntities surfaceEntities = new surfacedetectEntities())
                {
                    newlist = surfaceEntities.batch.AsNoTracking().Where(t => t.id > maxid).OrderByDescending(o => o.id).Take(1).ToList();//重新查询数据库中比当前批次id大的新记录，以此确认是否有新的批次
                }
                if (newlist.Count == 0)
                    return;

                //如果有新批次，先更新批次信息
                for (int i = 0; i < newlist.Count; i++)
                {
                    Batchlist.Insert(0, newlist[newlist.Count - i - 1]);//保持最新的批次被添加到最头部
                }
                CurrentBatch = Batchlist.First();
                //在主线程更新其他信息
                Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                {
                    //初始化相关信息
                    SteelDefectlist.Clear();
                    CurrentLeftEdge = 0;
                    latestSteelDefectInsertTime = null;
                    latestDefectInsertTime = null;
                    SubtotalByTypelist = new ObservableCollection<defectsubtotalbytype>();
                    updateSpeed();

                    while (Batchlist.Count > 1)//当有多余批次时开始循环删除批次信息，以及相关的缺陷列表中的信息
                    {
                        var lastmainid = Batchlist.Last().main_id;
                        Batchlist.Remove(Batchlist.Last());
                        var mainidlist = Batchlist.Select(t => t.main_id);
                        //拿到应保留列表中的批次号，以此为依据为删除非列表中的所有相关数据
                        var shouldBeRemovedImages = Currentlist.ToArray().Where(t => !mainidlist.Contains(t.Image_DefectList[0].main_id));
                        var count1 = shouldBeRemovedImages.Count();
                        foreach (var info in shouldBeRemovedImages)
                        {
                            Currentlist.Remove(info);
                        }
                        if (!SteelDefectlist.Any())
                            return;
                        var shouldBeRemovedSteelDefectInfos = SteelDefectlist.ToArray().Where(t => !mainidlist.Contains(t.First().main_id));
                        var count2 = shouldBeRemovedSteelDefectInfos.Count();
                        foreach (var item in shouldBeRemovedSteelDefectInfos)
                        {
                            SteelDefectlist.Remove(item);
                        }
                        Logger.Info($"删除多余批次{lastmainid},删除图片数量{count1}，删除钢材缺陷数量{count2}");

                    }
                    Logger.Info($"处理完成，当前钢材缺陷信息列表有{SteelDefectlist.Count}个，图片列表有{Currentlist.Count}个");
                }));
            }
            updateCurrentBatchInfo();//更新当前批次的信息（结论，其他更新信息）

        }

        private async Task QueryUpdateImageInfo()
        {
            try
            {
                //从旧往新处理多个批次，目前就一个批次
                foreach (batch batch in Batchlist.Take(1).Reverse())
                {
                    //每次查询更新10个图片缺陷
                    defectDataHelper = new DefectDataHelper();
                    var imagedefectinfolist = await defectDataHelper.getNewestDefectLists(batch.main_id, 10, latestDefectInsertTime);
                    defectDataHelper.setCurrentImageByImageType(imagedefectinfolist, CurrentImageType);

                    //Logger.Debug($"查询到图像缺陷:{imagedefectinfolist.Count()}");
                    if (imagedefectinfolist.Any())
                    {
                        imagedefectinfolist.First().IsFirst = true;
                        //更新该图像列表的最后时间，加1毫秒避免重复查询
                        latestDefectInsertTime = imagedefectinfolist.SelectMany(s => s.Image_DefectList).Max(m => m.insert_time).AddMilliseconds(1);
                        //Logger.Info($"更新的缺陷数量：{imagedefectinfolist.Count.ToString()},最后的缺陷时间是{(latestDefectInsertTime.HasValue ? ((DateTime)latestDefectInsertTime).ToLongTimeString() : "")}");
                        imagesFactory.AddImageInfos(imagedefectinfolist);

                        if (AutoRefreshCurrentImg && batch == Batchlist.First())//如果最新批次且开启主图自动更新则刷新当前主图
                        {
                            CurrentImg = imagedefectinfolist.FirstOrDefault();
                            CurrentDefect = CurrentImg.Image_DefectList[0];
                        }
                    }

                    //查询添加钢材缺陷
                    //永钢、兴橙、南南铝实时查询需要只查询冗余存储的钢材缺陷
                    var _steeldefectlist = await eshelper.GetSteelDefectsByMainID(batch.main_id, firstorlastinserttime: latestSteelDefectInsertTime);
                    _steeldefectlist = new ObservableCollection<steel_defect>(_steeldefectlist.Where(t => t.grade == "冗余存储"));
                    Logger.Debug($"查询到钢材缺陷:{_steeldefectlist.Count()}");
                    if (_steeldefectlist.Any())
                    {
                        //更新该钢材缺陷列表查询的最后时间，加1毫秒避免重复查询
                        latestSteelDefectInsertTime = _steeldefectlist.Max(m => m.insert_time).AddMilliseconds(1); ;
                        DoMenthodByDispatcher(new Action(() =>
                        {
                            SteelDefectlist.Insert(0, _steeldefectlist);
                        }));
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Error(e);
            }
        }

        private void updateCurrentBatchInfo()
        {
            var updateinfo = surfaceEntities.batch.Where(t => t.id == CurrentBatch.id).First();
            if (updateinfo != null)
            {
                CurrentBatch.conclusion = updateinfo.conclusion;
            }
        }

        private void updateSpeed()
        {
            if (Batchlist.Count > 0 && Batchlist.First().sd != null)
                StaticData.Speed = (double)Batchlist.First().sd;
        }
        private void updateAlertCount()
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {

                //IgnoreCount = (int)(total*r1/sum);
                WarningCount = SteelDefectlist.SelectMany(s => s).Where(t => t.grade == "警告").Count();
                AlertCount = SteelDefectlist.SelectMany(s => s).Where(t => t.grade == "报警").Count();
            }));
        }

        int i = 0;
        private void insertOrUpdateTestBatch()
        {

            if (i == 0)//插入批次
            {
                Random r = new Random();
                int score = r.Next(50, 100);
                var mainid = "X" + DateTime.Now.ToString("MMddHHmmss").Insert(8, "_");
                var newbatch = new batch()
                {
                    main_id = mainid,
                    user_custom_id = mainid,
                    gg = "33",
                    sd = 44,
                    cz = "线材",
                    score = score,
                    grade = score > 75 ? "优秀" : score > 60 ? "警告" : "警报",
                    ideal_length = r.Next(10000, 55555),
                    insert_time = DateTime.Now,
                    conclusion = "",
                    details = "划伤15处，周期性出现，请注意检查",
                    defect_num = 15,
                    suspected_num = 4,
                    warn_num = 6,
                    alert_num = 5,
                    SteelGrad="Test123"
                    //img_status = "cropped",
                };
                surfaceEntities.batch.Add(newbatch);

                surfaceEntities.steel_defect_amout.Add(new steel_defect_amout() { main_id = newbatch.main_id, defect_type = r.Next(1, 3), defect_num = r.Next(6), suspected_num = r.Next(6), warn_num = r.Next(6), alert_num = r.Next(6) });
                surfaceEntities.steel_defect_amout.Add(new steel_defect_amout() { main_id = newbatch.main_id, defect_type = r.Next(3, 5), defect_num = r.Next(6), suspected_num = r.Next(6), warn_num = r.Next(6), alert_num = r.Next(6) });
                surfaceEntities.steel_defect_amout.Add(new steel_defect_amout() { main_id = newbatch.main_id, defect_type = r.Next(5, 7), defect_num = r.Next(6), suspected_num = r.Next(6), warn_num = r.Next(6), alert_num = r.Next(6) });
                surfaceEntities.SaveChanges();
                StaticData.TestEntitity = new TestEntitity(newbatch.main_id);//同时初始化一个新的批次测试数据出来供展示
            }
            else
            {
                var currentbatchentity = surfaceEntities.batch.Find(CurrentBatch.id);
                currentbatchentity.conclusion = new Random().NextDouble() > 0.5 ? "-18-:32\r\n-14-:9\r\n-16-:6\r\n-12-:1\r\n-0-:1\r\n-1-:2\r\n-3-:1\r\n-4-:1\r\n" : "-18-:16\r\n-14-:5";
                surfaceEntities.SaveChanges();
            }
            i++;
            if (i > 8)//循环8次后，开始插入新批次
                i = 0;
        }

        private void autoDeleteMessage()
        {
            var period = int.Parse(StaticData.SysconfigList.Where(t => t.key == "msg_expiry_period").FirstOrDefault().value);//时间周期，分钟
            DoMenthodByDispatcher(() =>
            {
                AlertInfos.Where(t => t.insert_time < DateTime.Now.AddMinutes(-period)).ToList().ForEach(t => AlertInfos.Remove(t));
            });
        }
        public void SaveAlertInfos()
        {
            var json = JsonConvert.SerializeObject(AlertInfos);
            File.WriteAllText("alertinfos.json", json, Encoding.UTF8);
        }
        public void LoadAlertInfos()
        {
            if (File.Exists("alertinfos.json"))
            {
                var json = File.ReadAllText("alertinfos.json");
                foreach (var item in JsonConvert.DeserializeObject<ObservableCollection<AlertInfo>>(json))
                {
                    AlertInfos.Add(item);
                }
            }
        }

        #endregion


        #region 变量变化相关更新

        /// <summary>
        /// 更新当前图像，在UI上为主图信息
        /// </summary>
        private void updateCurrentImage()
        {
            CurrentImg = null;
            Task.Run(async () =>
            {
                var steelinfo = await defectDataHelper.getSteelDefectInfo(CurrentSteelDefect);//这里后面要排查是否给图像缺陷信息设置了默认缺陷
                Logger.Debug(steelinfo.Steel_defect.id + "--" + steelinfo.Imagedefectinfos.Count().ToString());
                if (steelinfo.Imagedefectinfos.Any())
                {
                    
                    defectDataHelper.setCurrentImageByImageType(steelinfo.Imagedefectinfos, CurrentImageType);
                    DoMenthodByDispatcher(() => { CurrentImg = steelinfo.Imagedefectinfos[0]; });
                }
            });
        }


        #endregion


        #region Command

        /// <summary>
        /// 更新钢材缺陷列表视图（在过滤器发生变化时）
        /// </summary>

        public void FilterView()
        {
            if (StaticData.CurrentDefectFilter != null)
            {
                var result = SteelDefectFilterHelper.GetFilteredSteelDefects(SteelDefectlist, StaticData.CurrentDefectFilter);
                SteelDefectlistView.Clear();
                SteelDefectlistView.Add(result);
            }
        }


        /// <summary>
        /// 输入自定义批次号
        /// </summary>
        public BaseCommand AddCusotmIdCommand
        {
            get => new BaseCommand((obj) =>
            {
                batch modifiedbatch = JsonConvert.DeserializeObject<batch>(JsonConvert.SerializeObject(CurrentBatch));
                var dlg = new VM_WindowTextBoxDlg("请输入批次号");
                dlg.ShowDialog();
                if ((dlg.UIElement as Window).DialogResult != true)
                    return;
                modifiedbatch.user_custom_id = dlg.Text;

                surfaceEntities.batch.AddOrUpdate(modifiedbatch);
                if (surfaceEntities.SaveChanges() != 1)
                {
                    MessageBox("保存失败");
                    Logger.Info($"批次{modifiedbatch.main_id}的用户定义批次号{modifiedbatch.user_custom_id}保存失败");
                }
                if (CurrentBatch.main_id == modifiedbatch.main_id)
                {
                    CurrentBatch.user_custom_id = modifiedbatch.user_custom_id;
                }
            });
        }

        public BaseCommand ConfirmAlertInfos
        {
            get => new BaseCommand((obj) =>
            {
                AlertInfos.All(t => { t.confirmed = true; return true; });
            });
        }

        public BaseCommand ClearAlertInfos
        {
            get => new BaseCommand((obj) =>
            {
                AlertInfos.Clear();
            });
        }

        public BaseCommand ConfirmAlertInfo
        {
            get => new BaseCommand((obj) =>
            {
                var currentinfo = AlertInfos.Where(t => t.id == obj.ToString());
                if (currentinfo.Count() == 1)
                {
                    currentinfo.First().confirmed = true;
                }
            });
        }

        public BaseCommand RemoveAlertInfo
        {
            get => new BaseCommand((obj) =>
            {
                var currentinfo = AlertInfos.Where(t => t.id == obj.ToString());
                if (currentinfo.Count() == 1)
                {
                    AlertInfos.Remove(currentinfo.First());
                }
            });
        }

        public BaseCommand GotoAlertDefect
        {
            get => new BaseCommand(async (obj) =>
            {
                var currentinfo = AlertInfos.Where(t => t.id == obj.ToString());
                if (!currentinfo.Any())
                    return;
                var alretinfo = currentinfo.First();
                switch (alretinfo.msg_type)
                {
                    case Msg_type.steel_defect:
                        //跳转到历史缺陷查询界面，跳转对应的批次号和缺陷号，如果缺陷号为空则只跳转到批次号
                        VM_WindowMain.GetInstance().GotoHistoryDefect(alretinfo.main_id, alretinfo.msg_id);
                        break;
                    case Msg_type.image_defect:
                        Logger.Info("收到一条图像缺陷报警");
                        CurrentImg = null;
                        //实时分析解析显示对应的图像缺陷
                        var imginfo=await defectDataHelper.getImageDefectInfo(alretinfo.msg_id);
                        if (imginfo==null)
                            MessageBox("没有找到这个缺陷");
                        else
                        {
                            defectDataHelper.setCurrentImageByImageType(new List<Imagedefectinfo>() { imginfo }, CurrentImageType);
                            CurrentImg = imginfo;
                            ShowFloatViewer=true;
                            ShowFloatViewer = false;
                        }
                        break;
                    case Msg_type.system_alert:
                        break;
                    default:
                        break;
                }

            });
        }
        public BaseCommand PopupHistoryAlert
        {
            get => new BaseCommand((obj) =>
            {
                new VM_WindowHistoryAlert().ShowDialog();
               
            });
        }


        #endregion


        #region 其他
        public void CloseConnection()
        {
            Connection.Stop();
        }
        private void CalcSubtotalByType()
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                var groupresult = SteelDefectlistView.SelectMany(s => s).GroupBy(g => g.type).Select(s => new defectsubtotalbytype { Type = s.Key, Name = StaticData.DefectTypes.Where(t => t.id == s.Key).First().name, Count = s.Count() });

                if (groupresult.Count() > 0)
                {
                    SubtotalByTypelist = new ObservableCollection<defectsubtotalbytype>(groupresult);
                    //Logger.Info(SubtotalByTypelist.Count.ToString() + "统计结果总数");
                }
            }));
        }

        private void updateShowAlertStatus()
        {
            Task.Run(async () =>
            {
                HttpClient client = new HttpClient() { Timeout = TimeSpan.FromSeconds(3) };
                var url = ConfigHelper.GetConfig("detect_url");
                var cancellationTokenSource = new CancellationTokenSource();
                var response = new HttpResponseMessage();
                try
                {
                    response = await client.PostAsync(url, new StringContent(JsonConvert.SerializeObject(new { alarmCancelledFlag = ShowAlert?1:0, signal = 3 }), Encoding.UTF8), cancellationTokenSource.Token);
                }
                catch (OperationCanceledException)
                {
                    if (StaticData.DataBase == DataFrom.Test)
                    {
                        response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                    }
                }
                if (!response.IsSuccessStatusCode)
                {
                    MessageBox("发送消息失败");
                }
            });
        }

        #endregion
    }



    public class defectsubtotalbytype : INotifyPropertyChanged
    {
        public int Type { get; set; }
        public string Name { get; set; }
        public int Count { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

    }








}
